package framework.classification.entities.lattice.erca;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;

import com.googlecode.erca.Attribute;
import com.googlecode.erca.BinaryAttribute;
import com.googlecode.erca.Entity;
import com.googlecode.erca.ErcaFactory;
import com.googlecode.erca.ValuedAttribute;
import com.googlecode.erca.clf.Concept;
import com.googlecode.erca.clf.ConceptLattice;
import com.googlecode.erca.framework.algo.Ceres;
import com.googlecode.erca.framework.algo.ConceptLatticeGenerator;

import com.googlecode.erca.framework.io.out.FormalContextToLatex;
import com.googlecode.erca.framework.io.out.LatticeToDot;
import com.googlecode.erca.rcf.FormalContext;
import com.googlecode.erca.rcf.RcfFactory;

import framework.classification.entities.ClAbstractEntity;
import framework.classification.entities.lattice.TreillisI;
import framework.entity.ACLEntity;
import framework.io.out.GraphViz;

public abstract class LatticeAbstractErca implements TreillisI {

	private ArrayList<Entity> entity;

	private ArrayList<Attribute> attributes;

	protected HashMap<String, String> realOperations;
	protected HashMap<String, String> abstractOperations;
	protected HashMap<String,ArrayList<String>> conceptToExtends;
	protected String superEntity;
	protected FormalContext context;
	protected ConceptLattice lattice;


	public LatticeAbstractErca(){

		realOperations = new HashMap<String, String>();
		abstractOperations = new HashMap<String, String>();
		conceptToExtends = new HashMap<String, ArrayList<String>>();
	}

	public abstract void calculateReduced(ClAbstractEntity table);

	public void computeTableRelation(ClAbstractEntity table) {

		entity = new ArrayList<Entity>();
		attributes = new ArrayList<Attribute>();
		context = RcfFactory.eINSTANCE.createFormalContext();


		//
		for (String aclAtt : table.getAttribut()){

			BinaryAttribute binAtt = ErcaFactory.eINSTANCE.createBinaryAttribute();
			binAtt.setName(aclAtt);
			attributes.add(binAtt);
			context.getAttributes().add(binAtt);
		}

		for (String aclObject : table.getEntity()){

			Entity ent = ErcaFactory.eINSTANCE.createEntity();
			ent.setName(aclObject);
			entity.add(ent);
			context.getEntities().add(ent);
		}

		computeRelation(table);

	}

	protected void computeRelation(ClAbstractEntity table) {
		for (int i = 0; i < this.entity.size(); i++) {
			for (int j = 0; j < this.attributes.size(); j++) {
				if (table.getTable()[j][i] != 0) {
					context.addPair(entity.get(i), attributes.get(j));
				}
			}
		}
	}

	public void computeLattice(ClAbstractEntity table,String latticeGeneration) {

		if (latticeGeneration.equals(LATTICE)){
			ConceptLatticeGenerator latgen = new ConceptLatticeGenerator(context);
			latgen.generateConceptLattice();
			lattice = latgen.getConceptLattice();
			lattice.setName(table.getName());
		}
		else if(latticeGeneration.equals(GSH)){
			Ceres latgen = new Ceres(context);
			latgen.generateConceptLattice();
			lattice = latgen.getConceptLattice();
			lattice.setName(table.getName());
		}

		calculateReduced(table);
	}

	public Boolean isParentConcept(String name, String name2) {


		Concept concept1 = lattice.getConcept(name);
		Concept concept2 = lattice.getConcept(name2);



		if ((concept1 == null) || (concept2 == null)) return false;

		for (int i = 0; i < concept1.getAllChildren().size(); i++) {
			if (concept1.getAllChildren().get(i).equals(concept2))
				return true;
		}

		return false;
	}

	public Boolean isParent(String n1,String n2){



		String strConceptN1 = null;
		if (realOperations.containsKey(n1))
			strConceptN1 = realOperations.get(n1);
		else strConceptN1 = abstractOperations.get(n1);


		String strConceptN2 = null;
		if (realOperations.containsKey(n2))
			strConceptN2 = realOperations.get(n2);
		else strConceptN2 = abstractOperations.get(n2);

		if ((strConceptN1 == null) || (strConceptN2 == null))
			return false;
		else
			return isParentConcept(strConceptN1, strConceptN2);



	}
	public ArrayList<String> getChildrenConcept(ClAbstractEntity table,String concept) {
		Concept concept1 = lattice.getConcept(concept);
		ArrayList<String> vect = new ArrayList<String>();
	
		for (Concept c : concept1.getAllChildren()) {
			if (concept1 != c){
				vect.add(c.getName());
			}
		}
		return vect;
	}

	public ArrayList<String> getParentConcept(ClAbstractEntity table,String concept) {
		Concept concept1 = lattice.getConcept(concept);
		ArrayList<String> vect = new ArrayList<String>();
		for (Concept c : concept1.getAllParents()) {
			vect.add(c.getName());
		}
		return vect;
	}


	public HashMap<String, String> getAbstractReduced(ClAbstractEntity table) {
		// TODO Auto-generated method stub
		return abstractOperations;
	}

	public HashMap<String, ArrayList<String>> getConceptToReduced(ClAbstractEntity table) {
		// TODO Auto-generated method stub
		return conceptToExtends;
	}

	public HashMap<String, String> getRealReduced(ClAbstractEntity table) {
		// TODO Auto-generated method stub
		return realOperations;
	}



	public ConceptLattice getConceptLattice() {
		return lattice;
	}

	public FormalContext getFormalContext(){
		return context;
	}

	public String getMaxSuperEntity(){
		return superEntity;
	}

}
